import 'package:flutter/material.dart';
import 'dart:core';
import '../widgets/screen_select_dialog.dart'; // 导入屏幕选择对话框组件
import 'signaling.dart'; // 导入信令处理模块
import 'package:flutter_webrtc/flutter_webrtc.dart'; // 导入WebRTC库，用于音视频通信

// CallSample类：视频通话示例页面，继承自StatefulWidget
class CallSample extends StatefulWidget {
  static String tag = 'call_sample'; // 页面标识
  final String host; // 信令服务器地址
  CallSample({required this.host});

  @override
  _CallSampleState createState() => _CallSampleState();
}

class _CallSampleState extends State<CallSample> {
  Signaling? _signaling; // 信令处理实例，用于建立和管理连接
  List<dynamic> _peers = []; // 在线用户列表
  String? _selfId; // 本地用户ID
  RTCVideoRenderer _localRenderer = RTCVideoRenderer(); // 本地视频渲染器
  RTCVideoRenderer _remoteRenderer = RTCVideoRenderer(); // 远程视频渲染器
  bool _inCalling = false; // 是否正在通话中
  Session? _session; // 当前通话会话
  DesktopCapturerSource? selected_source_; // 选中的屏幕共享源
  bool _waitAccept = false; // 是否正在等待对方接受邀请

  // 构造函数
  _CallSampleState();

  // 组件初始化
  @override
  initState() {
    super.initState();
    initRenderers(); // 初始化视频渲染器
    _connect(context); // 连接到信令服务器
  }

  // 初始化视频渲染器
  initRenderers() async {
    await _localRenderer.initialize(); // 初始化本地视频渲染器
    await _remoteRenderer.initialize(); // 初始化远程视频渲染器
  }

  // 组件停用，释放资源
  @override
  deactivate() {
    super.deactivate();
    _signaling?.close(); // 关闭信令连接
    _localRenderer.dispose(); // 释放本地视频渲染器资源
    _remoteRenderer.dispose(); // 释放远程视频渲染器资源
  }

  // 连接到信令服务器
  void _connect(BuildContext context) async {
    // 初始化信令实例并连接服务器
    _signaling ??= Signaling(widget.host, context)..connect();

    // 设置信令状态变化回调
    _signaling?.onSignalingStateChange = (SignalingState state) {
      switch (state) {
        case SignalingState.ConnectionClosed:
        case SignalingState.ConnectionError:
        case SignalingState.ConnectionOpen:
          break;
      }
    };

    // 设置通话状态变化回调
    _signaling?.onCallStateChange = (Session session, CallState state) async {
      switch (state) {
        case CallState.CallStateNew:
        // 新通话会话创建
          setState(() {
            _session = session;
          });
          break;
        case CallState.CallStateRinging:
        // 收到来电，显示接受对话框
          bool? accept = await _showAcceptDialog();
          if (accept!) {
            _accept(); // 接受通话
            setState(() {
              _inCalling = true;
            });
          } else {
            _reject(); // 拒绝通话
          }
          break;
        case CallState.CallStateBye:
        // 通话结束
          if (_waitAccept) {
            print('peer reject'); // 对方拒绝
            _waitAccept = false;
            Navigator.of(context).pop(false);
          }
          setState(() {
            _localRenderer.srcObject = null; // 清空本地视频源
            _remoteRenderer.srcObject = null; // 清空远程视频源
            _inCalling = false; // 更新通话状态
            _session = null; // 清空会话
          });
          break;
        case CallState.CallStateInvite:
        // 发出邀请，显示等待对话框
          _waitAccept = true;
          _showInvateDialog();
          break;
        case CallState.CallStateConnected:
        // 通话已连接
          if (_waitAccept) {
            _waitAccept = false;
            Navigator.of(context).pop(false);
          }
          setState(() {
            _inCalling = true;
          });
          break;
        case CallState.CallStateRinging:
          break;
      }
    };

    // 设置在线用户更新回调
    _signaling?.onPeersUpdate = ((event) {
      setState(() {
        _selfId = event['self']; // 更新本地用户ID
        _peers = event['peers']; // 更新在线用户列表
      });
    });

    // 设置本地媒体流回调
    _signaling?.onLocalStream = ((stream) {
      _localRenderer.srcObject = stream; // 设置本地视频源
      setState(() {});
    });

    // 设置远程媒体流添加回调
    _signaling?.onAddRemoteStream = ((_, stream) {
      _remoteRenderer.srcObject = stream; // 设置远程视频源
      setState(() {});
    });

    // 设置远程媒体流移除回调
    _signaling?.onRemoveRemoteStream = ((_, stream) {
      _remoteRenderer.srcObject = null; // 清空远程视频源
    });
  }

  // 显示来电接受对话框
  Future<bool?> _showAcceptDialog() {
    return showDialog<bool?>(
      context: context,
      builder: (context) {
        return AlertDialog(
          title: Text("title"), // 对话框标题
          content: Text("accept?"), // 对话框内容
          actions: <Widget>[
            // 拒绝按钮
            MaterialButton(
              child: Text(
                'Reject',
                style: TextStyle(color: Colors.red),
              ),
              onPressed: () => Navigator.of(context).pop(false),
            ),
            // 接受按钮
            MaterialButton(
              child: Text(
                'Accept',
                style: TextStyle(color: Colors.green),
              ),
              onPressed: () => Navigator.of(context).pop(true),
            ),
          ],
        );
      },
    );
  }

  // 显示等待对方接受对话框
  Future<bool?> _showInvateDialog() {
    return showDialog<bool?>(
      context: context,
      builder: (context) {
        return AlertDialog(
          title: Text("title"), // 对话框标题
          content: Text("waiting"), // 对话框内容
          actions: <Widget>[
            // 取消按钮
            TextButton(
              child: Text("cancel"),
              onPressed: () {
                Navigator.of(context).pop(false);
                _hangUp(); // 挂断通话
              },
            ),
          ],
        );
      },
    );
  }

  // 邀请用户进行通话或屏幕共享
  _invitePeer(BuildContext context, String peerId, bool useScreen) async {
    if (_signaling != null && peerId != _selfId) {
      _signaling?.invite(peerId, 'video', useScreen); // 发送邀请
    }
  }

  // 接受通话
  _accept() {
    if (_session != null) {
      _signaling?.accept(_session!.sid, 'video'); // 发送接受信号
    }
  }

  // 拒绝通话
  _reject() {
    if (_session != null) {
      _signaling?.reject(_session!.sid); // 发送拒绝信号
    }
  }

  // 挂断通话
  _hangUp() {
    if (_session != null) {
      _signaling?.bye(_session!.sid); // 发送结束通话信号
    }
  }

  // 切换摄像头
  _switchCamera() {
    _signaling?.switchCamera(); // 调用信令模块切换摄像头
  }

  // 选择屏幕共享源并开始共享
  Future<void> selectScreenSourceDialog(BuildContext context) async {
    MediaStream? screenStream;

    // 桌面平台
    if (WebRTC.platformIsDesktop) {
      // 显示屏幕选择对话框
      final source = await showDialog<DesktopCapturerSource>(
        context: context,
        builder: (context) => ScreenSelectDialog(),
      );
      if (source != null) {
        try {
          // 获取选中的屏幕流
          var stream =
          await navigator.mediaDevices.getDisplayMedia(<String, dynamic>{
            'video': {
              'deviceId': {'exact': source.id},
              'mandatory': {'frameRate': 30.0}
            }
          });
          // 添加屏幕共享结束事件监听
          stream.getVideoTracks()[0].onEnded = () {
            print(
                'By adding a listener on onEnded you can: 1) catch stop video sharing on Web');
          };
          screenStream = stream;
        } catch (e) {
          print(e);
        }
      }
    }
    // Web平台
    else if (WebRTC.platformIsWeb) {
      // 获取屏幕流
      screenStream =
      await navigator.mediaDevices.getDisplayMedia(<String, dynamic>{
        'audio': false,
        'video': true,
      });
    }

    // 开始屏幕共享
    if (screenStream != null) _signaling?.switchToScreenSharing(screenStream);
  }

  // 静音麦克风
  _muteMic() {
    _signaling?.muteMic(); // 调用信令模块静音麦克风
  }

  // 构建用户列表项
  _buildRow(context, peer) {
    var self = (peer['id'] == _selfId); // 判断是否是本地用户
    return ListBody(children: <Widget>[
      ListTile(
        // 显示用户名称和ID
        title: Text(self
            ? peer['name'] + ', ID: ${peer['id']} ' + ' [Your self]'
            : peer['name'] + ', ID: ${peer['id']} '),
        onTap: null,
        trailing: SizedBox(
          width: 100.0,
          child: Row(
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            children: <Widget>[
              // 视频通话按钮
              IconButton(
                icon: Icon(self ? Icons.close : Icons.videocam,
                    color: self ? Colors.grey : Colors.black),
                onPressed: () => _invitePeer(context, peer['id'], false),
                tooltip: 'Video calling',
              ),
              // 屏幕共享按钮
              IconButton(
                icon: Icon(self ? Icons.close : Icons.screen_share,
                    color: self ? Colors.grey : Colors.black),
                onPressed: () => _invitePeer(context, peer['id'], true),
                tooltip: 'Screen sharing',
              ),
            ],
          ),
        ),
        subtitle: Text('[' + peer['user_agent'] + ']'), // 显示用户代理信息
      ),
      Divider() // 分隔线
    ]);
  }

  // 构建UI界面
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      // 应用栏
      appBar: AppBar(
        title: Text('P2P Call Sample' +
            (_selfId != null ? ' [Your ID ($_selfId)] ' : '')), // 显示应用标题和本地用户ID
        actions: <Widget>[
          // 设置按钮
          IconButton(
            icon: const Icon(Icons.settings),
            onPressed: null,
            tooltip: 'setup',
          ),
        ],
      ),

      // 悬浮按钮位置
      floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,

      // 通话中显示的悬浮操作按钮
      floatingActionButton: _inCalling
          ? SizedBox(
        width: 240.0,
        child: Row(
          mainAxisAlignment: MainAxisAlignment.spaceBetween,
          children: <Widget>[
            // 切换摄像头按钮
            FloatingActionButton(
              child: const Icon(Icons.switch_camera),
              tooltip: 'Camera',
              onPressed: _switchCamera,
            ),
            // 屏幕共享按钮
            FloatingActionButton(
              child: const Icon(Icons.desktop_mac),
              tooltip: 'Screen Sharing',
              onPressed: () => selectScreenSourceDialog(context),
            ),
            // 挂断按钮
            FloatingActionButton(
              onPressed: _hangUp,
              tooltip: 'Hangup',
              child: Icon(Icons.call_end),
              backgroundColor: Colors.pink,
            ),
            // 静音按钮
            FloatingActionButton(
              child: const Icon(Icons.mic_off),
              tooltip: 'Mute Mic',
              onPressed: _muteMic,
            ),
          ],
        ),
      )
          : null,

      // 主内容区域
      body: _inCalling
      // 通话中显示视频画面
          ? OrientationBuilder(builder: (context, orientation) {
        return Container(
          child: Stack(children: <Widget>[
            // 远程视频，占据整个屏幕
            Positioned(
              left: 0.0,
              right: 0.0,
              top: 0.0,
              bottom: 0.0,
              child: Container(
                margin: EdgeInsets.fromLTRB(0.0, 0.0, 0.0, 0.0),
                width: MediaQuery.of(context).size.width,
                height: MediaQuery.of(context).size.height,
                child: RTCVideoView(_remoteRenderer),
                decoration: BoxDecoration(color: Colors.black54),
              ),
            ),
            // 本地视频，显示在左上角小窗口
            Positioned(
              left: 20.0,
              top: 20.0,
              child: Container(
                width: orientation == Orientation.portrait ? 90.0 : 120.0,
                height:
                orientation == Orientation.portrait ? 120.0 : 90.0,
                child: RTCVideoView(_localRenderer, mirror: true),
                decoration: BoxDecoration(color: Colors.black54),
              ),
            ),
          ]),
        );
      })
      // 未通话时显示在线用户列表
          : ListView.builder(
        shrinkWrap: true,
        padding: const EdgeInsets.all(0.0),
        itemCount: (_peers != null ? _peers.length : 0),
        itemBuilder: (context, i) {
          return _buildRow(context, _peers[i]);
        },
      ),
    );
  }
}